home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-06-14 | 6.5 KB | 241 lines | [TEXT/CWIE] |
- /*****************************************************************************/
- //
- // GetFolder.c
- //
- // This source code displays the standard file dialog box, modified to allow
- // the user to select a folder instead of a file.
- // Code provided by Andrew Duncan.
- //
- // Version 1.0
- //
- // Created: 13 May 1996
- // Modified: 14 June 1996
- //
- /*****************************************************************************/
-
- #define CustomGetFolderDialogID 129
- #define kSelectItem 13
-
- #define kCanSelectDesktop false
-
- #include "GetFolder.h"
-
-
- //
- // SameFile
- //
- static Boolean SameFile(FSSpec *spec1, FSSpec *spec2)
- {
- return ( (spec1->vRefNum == spec2->vRefNum)
- && (spec1->parID == spec2->parID)
- && (EqualString( spec1->name, spec2->name, false, true)) );
- }
-
-
- //
- // AppendStrToStr
- //
- static void AppendStrToStr(StringPtr dst, StringPtr src, unsigned char maxDstLen)
- {
- short offset = dst[0]+1;
- short size = src[0];
-
- if ( dst[0] + src[0] > maxDstLen) size = maxDstLen - dst[0];
- BlockMove( src+1, dst+offset, size);
- dst[0] += size;
- }
-
- static FSSpec gDeskFolderSpec;
-
- //
- // SetSelectButtonName
- //
- // Gets the "Select" button from the CustomGetFile dialog and
- // the filename string from the FSSpec parameter. It set the buttons name
- // to Select “filename”, truncating the filemane if needed. The button is
- // dimmed if kCanSelectDesktop==false and the FSSpec=the desktop folder.
- //
- static void SetSelectButtonName ( FSSpec *spec, DialogPtr theDlg )
- {
- Str255 btnName = "\p";
- Str255 selectString = "\pSelect"; // Should really be a resource...
- Str63 desktopFName = "\pDesktop"; // Ditto.
- Str63 selNameTrunc = "\p";
- Rect iRect;
- Handle iHndl;
- short btnWidth;
- short iType;
- Boolean hilited = true;
-
- if (SameFile(spec, &gDeskFolderSpec))
- {
- AppendStrToStr(selNameTrunc, desktopFName, 63) ;
- hilited = kCanSelectDesktop;
- }
- else
- AppendStrToStr(selNameTrunc, spec->name, 63) ;
-
-
- GetDItem(theDlg,kSelectItem,&iType,&iHndl,&iRect);
-
- /* truncate select name to fit in button */
- btnWidth = iRect.right - iRect.left;
- btnWidth -= StringWidth(selectString);
- btnWidth -= StringWidth("\p “” ");
- TruncString(btnWidth, selNameTrunc, smTruncMiddle);
-
- /* build button name string */
- AppendStrToStr(btnName, selectString, 255) ;
- AppendStrToStr(btnName, "\p “", 255) ;
- AppendStrToStr(btnName, selNameTrunc, 255) ;
- AppendStrToStr(btnName, "\p”", 255) ;
-
- SetCTitle((ControlRef)iHndl, btnName);
-
- if (hilited)
- HiliteControl((ControlRef)iHndl,0);
- else
- HiliteControl((ControlRef)iHndl,255);
- }
-
-
- //
- // MyDlgHook
- //
- static pascal short MyDlgHook ( short item, DialogPtr theDlg, void* userData )
- {
- StandardFileReply* reply;
- FSSpec curSpec;
- OSType refCon;
- static FSSpec lastSpec; /* Remember lastSpec so that we don't update Select button needlessly */
- OSErr err;
-
- refCon = GetWRefCon(theDlg);
- if (refCon != sfMainDialogRefCon)
- return item;
-
- reply = (StandardFileReply*) userData;
-
- if (item == sfHookFirstCall) /* if the dialog is just about to appear */
- lastSpec.vRefNum = -9999; /* init to ridiculous value */
-
- if (item == sfHookNullEvent) /* if we got a NullEvent */
- {
- if ( !SameFile( &(reply->sfFile), &lastSpec) )
- {
- curSpec = reply->sfFile;
- err = FSMakeFSSpec(curSpec.vRefNum, curSpec.parID, curSpec.name, &curSpec);
- // MakeCanonFSSpec(&curSpec);
- SetSelectButtonName(&curSpec, theDlg);
- lastSpec = reply->sfFile ;
- }
- }
-
- if (item == kSelectItem) item = sfItemOpenButton;
-
- return item;
- }
-
-
- //
- // MyFilterAllFiles
- //
- // A file filter proc that removes everything but directories from the
- // CustomGetFile list. This means that only Folders, Volumes, or Aliases of
- // Folders or Volumes will appear in the list.
- //
- static pascal Boolean MyFilterAllFiles(CInfoPBPtr pb, void* /*myDataPtr*/)
- {
- if (pb->hFileInfo.ioFlAttrib & (1 << 4)) /* file is a directory */
- return false;
- return true;
- }
-
-
- //
- // CustomGetFolder
- //
- OSErr CustomGetFolder(StandardFileReply *reply)
- {
- Point where = {-1,-1}; /* center dialog on main screen */
- OSErr err;
- Boolean targetIsFolder,wasAliased;
- FileFilterYDUPP ffUPP;
- DlgHookYDUPP dhUPP;
-
-
- err = FindFolder(kOnSystemDisk,
- kDesktopFolderType,
- kDontCreateFolder,
- &gDeskFolderSpec.vRefNum,
- &gDeskFolderSpec.parID);
- gDeskFolderSpec.name[0] = '\0';
- err = FSMakeFSSpec(gDeskFolderSpec.vRefNum, gDeskFolderSpec.parID, gDeskFolderSpec.name, &gDeskFolderSpec);
-
-
- ffUPP = NewFileFilterYDProc(MyFilterAllFiles);
- dhUPP = NewDlgHookYDProc(MyDlgHook);
-
-
- CustomGetFile( ffUPP, /* file filter proc */
- -1, /* number of file types */
- nil, /* array of file types */
- reply, /* the StandardFileReply structure */
- CustomGetFolderDialogID, /* the dialog's ID */
- where, /* position of dialog on screen */
- dhUPP, /* the Dialog Hook procedure */
- nil, /* no modal dialog filterProc */
- nil, /* no activeListPtr */
- nil, /* no activateProc */
- reply /* yourDataPtr: pass reply in so that */
- ); /* MyDlgHook() can access current info */
-
- if ( !reply->sfGood ) /* if the user hit cancel button */
- return noErr ; /* then nothing more to do so return */
-
-
- // If we were inside a folder with no subfolders, reply->sfFile.parID will be the
- // ID of the folder (not that of its parent) and the string will be null. In that
- // case, don’t try to resolve the alias.
- if (reply->sfFile.name[0] != '\0')
- {
- err = ResolveAliasFile( &(reply->sfFile), true, &targetIsFolder, &wasAliased);
- if (err) return err ;
- }
-
-
- // If is not a directory or volume (e.g. we were inside a folder with no subfolders.
- if ( !reply->sfIsFolder && !reply->sfIsVolume )
- {
- FSSpec tempSpec;
- CInfoPBRec infoPB;
- Boolean IsDirectory;
-
- tempSpec = reply->sfFile;
- if (tempSpec.name[0] != '\0') return; //err
-
- infoPB.dirInfo.ioNamePtr = tempSpec.name;
- infoPB.dirInfo.ioVRefNum = tempSpec.vRefNum;
- infoPB.dirInfo.ioDrDirID = tempSpec.parID;
- infoPB.dirInfo.ioFDirIndex = -1;
-
- err = PBGetCatInfo( &infoPB, false );
- if (err) return err ;
-
- tempSpec.parID = infoPB.dirInfo.ioDrParID ;
-
- // make sure that it's a directory
- IsDirectory = (infoPB.dirInfo.ioFlAttrib & 0x10) ;
- if ( !IsDirectory ) return; //err
-
- reply->sfFile = tempSpec ;
- reply->sfScript = infoPB.dirInfo.ioDrFndrInfo.frScript ;
- reply->sfFlags = infoPB.dirInfo.ioDrUsrWds.frFlags ;
- reply->sfIsFolder = (tempSpec.parID == 1) ? (0x00) : (0xFF) ;
- reply->sfIsVolume = (tempSpec.parID == 1) ? (0xFF) : (0x00) ; ;
- }
-
- return noErr;
- }
-
-